package com.web.option.service;

import com.web.account.entity.Account;
import com.web.account.service.AccountService;
import com.web.common.BaseResult;
import com.web.common.enums.BaseStatus;
import com.web.option.entity.Option;
import com.web.option.mapper.OptionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.List;
import java.util.logging.Logger;

/**
 * @author wenzhuo
 * @create 2024-07-07 2024/7/7
 */
@Service
public class OptionService {


    Logger logger = Logger.getLogger(this.getClass().getName());

    @Autowired
    private AccountService accountService;

    @Resource
    private OptionMapper optionMapper;

    @Transactional
    public BaseResult handleOption(Option option) {

        //根据strikeRate重新计算Buy/Sell金额
        BigDecimal putAmount = option.getStrikeRate().multiply(option.getPutAmount()).setScale(2, RoundingMode.HALF_DOWN);
        BigDecimal callAmount= option.getStrikeRate().multiply(option.getCallAmount()).setScale(2, RoundingMode.HALF_DOWN);
        logger.info("reCalculate buyAmount:" + putAmount);
        logger.info("reCalculate callAmount:" + callAmount);
        option.setPutAmount(putAmount);
        option.setCallAmount(callAmount);

        //新增option交易
        if(generateOption(option) != 1){
            return new BaseResult(BaseStatus.OPTION_INSERT_FAILED.getCode(),BaseStatus.OPTION_INSERT_FAILED.getDesc());
        }

        return new BaseResult(BaseStatus.SUCCESS.getCode(),BaseStatus.OPTION_INSERT_SUCCESS.getDesc());
    }


    public Integer generateOption(Option option) {
        return optionMapper.addOption(option);
    }

    public List<Option> getOptionList(Option option) {
        return optionMapper.getOptionList(option);
    }

    public List<Option> getOptionListByStatusNor(LocalDate expireDate) {
        return optionMapper.getOptionListByStatusNor(expireDate);
    }

    public Integer rejectOption(Integer optionNumber, String userName,String remark) {
        return optionMapper.updateStatus(optionNumber,userName,remark);
    }

    public Option findOptionByOptionNo(Integer optionNumber) {
        return optionMapper.getOptionByOptionNo(optionNumber);
    }

    @Transactional
    public BaseResult confirmOption(Option option) {

        //根据Currency、Buy_Sell、客户号查询出账户
        Account buyAccount = accountService.getBuyAccountByCurrency(option.getPutCcy(),option.getCustomerNo());
        Account sellAccount = accountService.getSellAccountByCurrency(option.getCallCcy(),option.getCustomerNo());

        if(buyAccount == null || sellAccount== null){
            return new BaseResult(BaseStatus.ACCOUNT_DATA_EXCEPTION.getCode(),BaseStatus.ACCOUNT_DATA_EXCEPTION.getDesc());
        }

        //判断合约中的Sell扣账账户余额是否足够
        if(sellAccount.getAccountBalance().compareTo(option.getCallAmount()) < 0){
            return new BaseResult(BaseStatus.SELL_AMOUNT_NOT_ENOUGH.getCode(),BaseStatus.SELL_AMOUNT_NOT_ENOUGH.getDesc());
        }

        //扣账账户和入账账户增加/减少对应的金额
        BigDecimal addToBalance = buyAccount.getAccountBalance().add(option.getPutAmount());
        buyAccount.setAccountBalance(addToBalance);

        BigDecimal subtractToBalance = sellAccount.getAccountBalance().subtract(option.getCallAmount());
        sellAccount.setAccountBalance(subtractToBalance);

        if(accountService.increaseAmount(buyAccount) <= 0 || accountService.reduceAmount(sellAccount) <= 0){
            return new BaseResult(BaseStatus.OPTION_CALL_OR_PUT_NO_FAILED.getCode(),BaseStatus.OPTION_CALL_OR_PUT_NO_FAILED.getDesc());
        }

        //修改Option交易数据
        if(optionMapper.updateStatusNor(option) <= 0){
            return new BaseResult(BaseStatus.OPTION_CONFIRM_FAILED.getCode(),BaseStatus.OPTION_CONFIRM_FAILED.getDesc());
        };

        return new BaseResult(BaseStatus.SUCCESS.getCode(),BaseStatus.OPTION_CONFIRM_SUCCESS.getDesc());
    }

    public Integer settlementOption(List<Option> optionsNor) {

        return optionMapper.updateStatusDon(optionsNor);
    }
}
